/**
 * Copyright 2009 Henning Teek, Ingo Renner
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.googlecode.chigs.web.common.modal;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;

import org.apache.commons.codec.binary.Hex;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.form.upload.FileUpload;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.FileCopyUtils;

/**
 * 
 * @author Ingo Renner
 * @author Henning Teek
 *
 */
public abstract class FileUploadPanel extends Panel {
    private static Logger log =  LoggerFactory.getLogger(FileUploadPanel.class);

	public FileUploadPanel(String id) {
		super(id);
		add(createUploadPanel());
	}

	private UploadPanel createUploadPanel() {
		return new UploadPanel("upload"){
			@Override
			public String onFileUploaded(FileUpload upload) {
				if (upload != null) {
					try {
						final String digest = doImport(upload);
						if (digest!=null) {
							getFeedbackPanel().info("Upload ok");
							handleUploadedData(digest, upload);
						} else {
							getFeedbackPanel().error("Datei konnte nicht erfolgreich gespeichert werden.");
							handleUploadFailed(upload);
						}
					} catch (Exception e) {
						log.error(e.getMessage(),e);
						getFeedbackPanel().error(e.toString());
					}
				} else {					
					getFeedbackPanel().error("Bitte erst eine Datei auswählen.");
				}
				return "";
			}

			@Override
			public void onUploadFinished(AjaxRequestTarget target, String filename, String newFileUrl) {
				//when upload is finished, will be called
				FileUploadPanel.this.onUploadFinished(target, filename, newFileUrl);
			}
		};
	}
	
	protected abstract void onUploadFinished(AjaxRequestTarget target, String filename, String newFileUrl);
	
	protected abstract FeedbackPanel getFeedbackPanel();
	
	protected abstract void handleUploadedData(String digest, FileUpload upload);
	
	protected abstract void handleUploadFailed(FileUpload upload);
	
	public String doImport(FileUpload upload) {
		try {
			final File temp = createTmpFile();
			// Jetzt speichern
			// Save to new file
			upload.writeTo(temp);
			// Digest berechnen
			String digest = createDigest(temp);
			// TODO check for existing data with same digest
			final File storehouse = new File("storehouse");
			if (!storehouse.exists()) {
				storehouse.mkdirs();
			}
			File data = new File(storehouse, digest);
			if( data.exists() ) {
				data.delete();
				log.info("Data already exists, it will be replaced.");
			}
			createFile(data);
			FileCopyUtils.copy(temp, data);
			temp.delete();
			log.info("saved file: " + upload.getClientFileName() + " to file: " + digest);
			return digest;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}

	}

	private void createFile(File file) throws IOException {
		if( file.getParentFile()!= null && !file.getParentFile().exists() ) {
			file.getParentFile().mkdirs(); 
		}
		file.createNewFile();
	}

	private File createTmpFile() throws IOException {
		// Create temp file.
		final String unique = String.valueOf(System.currentTimeMillis());
		final File tempDir = new File("temp");
		if (!tempDir.exists()) {
			tempDir.mkdirs();
		}
		final File temp = File.createTempFile(unique.substring(0, unique.length()/2), unique.substring(unique.length()/2+1), tempDir);
		temp.createNewFile();
		// Delete temp file when program exits.
		temp.deleteOnExit();
		return temp;
	}

	public static String createDigest(File file) {
		byte[] result;
		InputStream in;
		try {
			MessageDigest messageDigest = MessageDigest.getInstance( "SHA", "SUN" ); 
			in = new FileInputStream(file);
			{ 
				byte[] md = new byte[ 8192 ]; 

				for ( int n = 0; (n = in.read( md )) > -1; ) 
					messageDigest.update( md, 0, n ); 

				result =  messageDigest.digest(); 
			}
			return toHexString(result);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchProviderException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static  String toHexString(byte[] md5hashAsByteArray){
		final Hex hex = new Hex();
		return new String(hex.encode(md5hashAsByteArray )); 
	}

}